package hu.mapro.flang.gwt.service;

import hu.mapro.flang.gwt.domain.client.AutoBeans;
import hu.mapro.flang.gwt.domain.client.AutoBeans.Types;
import hu.mapro.flang.gwt.domain.client.AutoBeans.UserFields;
import hu.mapro.flang.gwt.domain.server.Attempt;
import hu.mapro.flang.gwt.domain.server.AttemptError;
import hu.mapro.flang.gwt.domain.server.Book;
import hu.mapro.flang.gwt.domain.server.Exercise;
import hu.mapro.flang.gwt.domain.server.Practice;
import hu.mapro.flang.gwt.domain.server.User;
import hu.mapro.flang.gwt.domain.server.UserPrivilege;
import hu.mapro.gwtui.server.GwtUiServiceLayerDecorator;
import hu.mapro.gwtui.server.data.DaoBase;
import hu.mapro.gwtui.shared.data.DataTypeUtils;
import hu.mapro.jpa.model.client.domain.FetchPlanCreator;
import hu.mapro.jpa.model.client.domain.FetchRequestFactory;
import hu.mapro.jpa.model.domain.client.AutoBeans.FactoryByClass;
import hu.mapro.jpa.model.domain.client.AutoBeans.FactoryInit;
import hu.mapro.jpa.model.server.JpaGwtLister;
import hu.mapro.model.LongId;
import hu.mapro.model.impl.FieldChainImpl;
import hu.mapro.model.meta.EntityType;
import hu.mapro.model.meta.FieldChain;

import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.server.ServiceLayer;
import com.google.web.bindery.requestfactory.server.SimpleRequestProcessor;
import com.google.web.bindery.requestfactory.server.testing.InProcessRequestTransport;
import com.google.web.bindery.requestfactory.vm.RequestFactorySource;

public class DomainService {

	@Component
	public class PracticeService extends DaoBase<Practice> {

		public PracticeService() {
			super(Practice.class, LongId.KEYPROVIDER);
		}
		
	}

	@Component
	public class AttemptService extends DaoBase<Attempt> {

		public AttemptService() {
			super(Attempt.class, LongId.KEYPROVIDER);
		}
		
	}

	@Component
	public class AttemptErrorService extends DaoBase<AttemptError> {

		public AttemptErrorService() {
			super(AttemptError.class, LongId.KEYPROVIDER);
		}
		
	}

	@Component
	public static class BookService extends DaoBase<Book> {

		public BookService() {
			super(Book.class, LongId.KEYPROVIDER);
		}
		
	}	

	@Component
	public static class UserService extends DaoBase<User> {

		@Resource
		ApplicationContext applicationContext;

		public UserService() {
			super(User.class, LongId.KEYPROVIDER);
		}
		
		@Override
		public List<User> list() {
			ServiceLayer serviceLayer = ServiceLayer.create(new GwtUiServiceLayerDecorator() {
				@Override
				protected <T> T lookup(Class<T> clazz) {
					return applicationContext.getBean(clazz);
				}
			});
			SimpleRequestProcessor processor = new SimpleRequestProcessor(serviceLayer);
			EventBus eventBus = new SimpleEventBus();
			FetchRequestFactory f = RequestFactorySource.create(FetchRequestFactory.class);
			f.initialize(eventBus, new InProcessRequestTransport(processor));	
			
			Collection<FieldChain<AutoBeans.User, ?, ?>> chains = Lists.newArrayList();
			chains.add(FieldChainImpl.create(UserFields.privileges));
			
			Function<EntityType<?>, Class<?>> function = new Function<EntityType<?>, Class<?>>() {
				@Override
				public Class<?> apply(EntityType<?> input) {
					if (input==Types.user) return User.class;
					if (input==Types.userPrivilege) return UserPrivilege.class;
					return null;
				}
			};
			FactoryInit factoryInit = new FactoryInit(new FactoryByClass(DataTypeUtils.forRF(f.requestContext())));
			return JpaGwtLister.list(entityManager, Types.user, function , FetchPlanCreator.createFetchPlan(factoryInit, chains ));
			
		}

	}	

	@Component
	public static class UserPrivilegeService extends DaoBase<UserPrivilege> {

		public UserPrivilegeService() {
			super(UserPrivilege.class, LongId.KEYPROVIDER);
		}

	}	

	@Component
	public static class ExerciseService extends DaoBase<Exercise> {

		public ExerciseService() {
			super(Exercise.class, LongId.KEYPROVIDER);
		}

	}	
//	@Component
//	public static class ExerciseService  {
//	}	
	
	
}
